unit SmallStruct.Database.TSSDataSet;

interface

uses dialogs,
  Classes,
  DB,
  Provider,
  DBClient,
  SmallStruct.Core,
  SmallStruct.Core.TSSObject,
  SmallStruct.Database,
  SmallStruct.Tools;

type
  TSSDataSet = class(TSSObject, ISSDataSet, ISSDataSetModifiable)
  private
    _DataSet: TDataSet;
    _DataSetProvider: TDataSetProvider;
    _ClientDataSet: TClientDataSet;
  public
    function GetBooleanValue(const AFieldName: string): Boolean;
    function GetCount: Integer;
    function GetCurrencyValue(const AFieldName: string): Currency;
    function GetDataSet: TDataSet;
    function GetDateTimeValue(const AFieldName: string): TDateTime;
    function GetDoubleValue(const AFieldName: string): Double;
    function GetFieldCount: Integer;
    function GetFieldName(const AIndex: Integer): string;
    function GetIntegerValue(const AFieldName: string): Integer;
    function GetData: ISSRecord; overload;
    function GetData(ABookmark: TStringList): ISSObjectContainer; overload;
    function GetStringValue(const AFieldName: string): string;
    function GetValue(const AFieldName: string): Variant;
    function GetValueAverage(const AFieldName: string): Variant;
    function GetValueSum(const AFieldName: string): Variant;
    function GetValueMax(const AFieldName: string): Variant;
    function GetValueMin(const AFieldName: string): Variant;
    function IsBof: Boolean;
    function IsEof: Boolean;
    function Locate(const KeyField: string; const KeyFieldValue: variant): Boolean;
    procedure SetFilter(const AFilter: string);
    procedure SetIndex(const AFieldName: string);
    procedure Next;
    procedure Prior;
    procedure First;
    procedure Last;
  public
    procedure Append;
    procedure Delete;
    procedure SetValue(const AFieldName: string; Value: Variant);
    procedure SetNull(const AFieldName: string);
    procedure Save;
    procedure edit;
  public
    procedure InitDataSet(Data: Variant); overload;
    procedure InitDataSet(AClientDataSet: TClientDataSet); overload;
    procedure InitDataSet(ADataSet: TDataSet); overload;
  public
    destructor Destroy; override;
  end;

implementation

uses SysUtils,
  Variants,
  SmallStruct.Core.TSSObjectContainer;

{ TSSDataSet }

procedure TSSDataSet.Append;
begin
  _ClientDataSet.Append;
end;

procedure TSSDataSet.Delete;
begin
  _ClientDataSet.Delete;
end;

destructor TSSDataSet.Destroy;
begin
  if Assigned(_DataSet) then
    _DataSet.Free;
  inherited;
end;

procedure TSSDataSet.edit;
begin
  _ClientDataSet.Edit;
end;

procedure TSSDataSet.First;
begin
  _ClientDataSet.First;
end;

function TSSDataSet.GetBooleanValue(const AFieldName: string): Boolean;
begin
  Result := _ClientDataSet.FieldByName(AFieldName).AsInteger <> 0;
end;

function TSSDataSet.GetCount: Integer;
begin
  Result := _ClientDataSet.RecordCount;
end;

function TSSDataSet.GetCurrencyValue(const AFieldName: string): Currency;
begin
  Result := _ClientDataSet.FieldByName(AFieldName).AsCurrency
end;

function TSSDataSet.GetData(ABookmark: TStringList): ISSObjectContainer;
var
  Index: Integer;
begin
  _ClientDataSet.DisableControls;

  Result := TSSObjectContainer.Create(nil);

  for Index := 0 to ABookmark.Count - 1 do
  begin
    _ClientDataSet.Bookmark := ABookmark.Strings[Index];
    Result.AppendObject(IntToStr(Index), GetData.GetObjectInstance);
  end;
end;

function TSSDataSet.GetDataSet: TDataSet;
begin
  Result := _ClientDataSet;
end;

function TSSDataSet.GetDateTimeValue(const AFieldName: string): TDateTime;
begin
  Result := _ClientDataSet.FieldByName(AFieldName).AsDateTime;
end;

function TSSDataSet.GetDoubleValue(const AFieldName: string): Double;
begin
  Result := _ClientDataSet.FieldByName(AFieldName).AsFloat;
end;

function TSSDataSet.GetFieldCount: Integer;
begin
  Result := _ClientDataSet.FieldCount;
end;

function TSSDataSet.GetFieldName(const AIndex: Integer): string;
begin
  Result := _ClientDataSet.Fields[AIndex].FieldName;
end;

function TSSDataSet.GetIntegerValue(const AFieldName: string): Integer;
begin
  Result := _ClientDataSet.FieldByName(AFieldName).AsInteger;
end;

function TSSDataSet.GetData: ISSRecord;
var
  Index: Integer;
begin
  Result := TSSRecord.Create(nil);

  for Index := 0 to _ClientDataSet.FieldCount - 1 do
    Result.AppendValue(_ClientDataSet.Fields[Index].FieldName, _ClientDataSet.Fields[Index].Value);
end;

function TSSDataSet.GetStringValue(const AFieldName: string): string;
begin
  Result := _ClientDataSet.FieldByName(AFieldName).AsString;
end;

function TSSDataSet.GetValue(const AFieldName: string): Variant;
begin
  Result := _ClientDataSet.FieldByName(AFieldName).Value;
end;

function TSSDataSet.GetValueAverage(const AFieldName: string): Variant;
var
  Aggregate: TAggregate;
  AggregateName: string;
begin
  Aggregate := _ClientDataSet.Aggregates.Add;
  try
    AggregateName := UpperCase(Trim(AFieldName)) + '_AVG';
    Aggregate.Expression := 'AVG(' + AFieldName + ')';
    Aggregate.Active := True;
    Aggregate.Visible := True;
    _ClientDataSet.AggregatesActive := True;
    Result := Aggregate.Value;
  finally
    _ClientDataSet.AggregatesActive := False;
    _ClientDataSet.Aggregates.Clear;
  end;
end;

function TSSDataSet.GetValueMax(const AFieldName: string): Variant;
var
  Aggregate: TAggregate;
  AggregateName: string;
begin
  Aggregate := _ClientDataSet.Aggregates.Add;
  try
    AggregateName := UpperCase(Trim(AFieldName)) + '_MAX';
    Aggregate.Expression := 'MAX(' + AFieldName + ')';
    Aggregate.Active := True;
    Aggregate.Visible := True;
    _ClientDataSet.AggregatesActive := True;
    Result := Aggregate.Value;
  finally
    _ClientDataSet.AggregatesActive := False;
    _ClientDataSet.Aggregates.Clear;
  end;
end;

function TSSDataSet.GetValueMin(const AFieldName: string): Variant;
var
  Aggregate: TAggregate;
  AggregateName: string;
begin
  Aggregate := _ClientDataSet.Aggregates.Add;
  try
    AggregateName := UpperCase(Trim(AFieldName)) + '_MIN';
    Aggregate.Expression := 'MIN(' + AFieldName + ')';
    Aggregate.Active := True;
    Aggregate.Visible := True;
    _ClientDataSet.AggregatesActive := True;
    Result := Aggregate.Value;
  finally
    _ClientDataSet.AggregatesActive := False;
    _ClientDataSet.Aggregates.Clear;
  end;
end;

function TSSDataSet.GetValueSum(const AFieldName: string): Variant;
var
  Aggregate: TAggregate;
  AggregateName: string;
begin
  Aggregate := _ClientDataSet.Aggregates.Add;
  try
    AggregateName := UpperCase(Trim(AFieldName)) + '_SUM';
    Aggregate.Expression := 'SUM(' + AFieldName + ')';
    Aggregate.Active := True;
    Aggregate.Visible := True;
    _ClientDataSet.AggregatesActive := True;
    Result := Aggregate.Value;
  finally
    _ClientDataSet.AggregatesActive := False;
    _ClientDataSet.Aggregates.Clear;
  end;
end;

procedure TSSDataSet.InitDataSet(AClientDataSet: TClientDataSet);
begin
  _ClientDataSet := AClientDataSet;
end;

procedure TSSDataSet.InitDataSet(ADataSet: TDataSet);
begin
  _DataSet := ADataSet;
  _DataSetProvider := TDataSetProvider.Create(Self);
  _DataSetProvider.Options := _DataSetProvider.Options + [poIncFieldProps];
  _DataSetProvider.DataSet := _DataSet;
  _DataSetProvider.Name := '_DataSetProvider';

  _ClientDataSet := TClientDataSet.Create(Self);
  _ClientDataSet.AutoCalcFields := False;
  _ClientDataSet.ObjectView := True;
  _ClientDataSet.ReadOnly := False;

  _ClientDataSet.ProviderName := _DataSetProvider.Name;

  //  _ClientDataSet.Active := True;
  //  _ClientDataSet.Edit;
end;

function TSSDataSet.IsBof: Boolean;
begin
  Result := _ClientDataSet.Bof;
end;

function TSSDataSet.IsEof: Boolean;
begin
  Result := _ClientDataSet.Eof;
end;

procedure TSSDataSet.Last;
begin
  _ClientDataSet.Last;
end;

function TSSDataSet.Locate(const KeyField: string; const KeyFieldValue: variant): Boolean;
begin
  Result := _ClientDataSet.Locate(KeyField, KeyFieldValue, []);
end;

procedure TSSDataSet.Next;
begin
  _ClientDataSet.Next;
end;

procedure TSSDataSet.Prior;
begin
  _ClientDataSet.Prior;
end;

procedure TSSDataSet.InitDataSet(Data: Variant);
begin
  _ClientDataSet := TClientDataSet.Create(Self);
  _ClientDataSet.AutoCalcFields := False;
  _ClientDataSet.ObjectView := False;
  _ClientDataSet.ReadOnly := False;

  _ClientDataSet.AppendData(Data, True);
end;

procedure TSSDataSet.Save;
begin
  _ClientDataSet.ApplyUpdates(0);
end;

procedure TSSDataSet.SetFilter(const AFilter: string);
begin
  if Length(AFilter) = 0 then
    _ClientDataSet.Filtered := False
  else
  begin
    _ClientDataSet.Filter := AFilter;
    _ClientDataSet.Filtered := True;
  end;
end;

procedure TSSDataSet.SetIndex(const AFieldName: string);
begin
  _ClientDataSet.IndexFieldNames := AFieldName;
end;

procedure TSSDataSet.SetNull(const AFieldName: string);
begin
  _ClientDataSet.FieldByName(AFieldName).Value := Unassigned;
end;

procedure TSSDataSet.SetValue(const AFieldName: string; Value: Variant);
begin
  _ClientDataSet.FieldByName(AFieldName).Value := Value;
end;

end.
